#include <GL/glew.h>
#include "screenbox.h"
#include "global.h"
#include "staticfunctions.h"

ScreenBox::ScreenBox()
{
  m_screenboxes.clear();
}

ScreenBox::~ScreenBox() { clear(); }

bool ScreenBox::isValid() { return (m_screenboxes.count() > 0); }

void
ScreenBox::clear()
{
  for(int i=0; i<m_screenboxes.count(); i++)
    m_screenboxes[i]->removeFromMouseGrabberPool();

  for(int i=0; i<m_screenboxes.count(); i++)
    delete m_screenboxes[i];

  m_screenboxes.clear();
}

QList<ScreenBoxObject>
ScreenBox::screenboxes()
{
  QList<ScreenBoxObject> scalist;
  for(int i=0; i<m_screenboxes.count(); i++)
    scalist.append(m_screenboxes[i]->screenbox());

  return scalist;
}


bool
ScreenBox::grabsMouse()
{
  for(int i=0; i<m_screenboxes.count(); i++)
    {
      if (m_screenboxes[i]->grabsMouse())
	return true;
    }
  return false;
}

void
ScreenBox::add(ScreenBoxObject cap)
{
  if (m_screenboxes.count() > 0)
    {
      QMessageBox::information(0, "Error", "Sorry cannot have more than one screen boxes.");
      return;
    }
  ScreenBoxGrabber *cmg = new ScreenBoxGrabber();
  cmg->setScreenBox(cap);
  m_screenboxes.append(cmg);
}

void
ScreenBox::setScreenBox(QList<ScreenBoxObject> caps)
{
  clear();

  for(int i=0; i<caps.count(); i++)
    add(caps[i]);
}

#define VECPRODUCT(a, b) Vec(a.x*b.x, a.y*b.y, a.z*b.z)
void
ScreenBox::draw(QGLViewer *viewer)
{
  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);      
  glEnable(GL_BLEND);
  glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // back to front
  glDepthMask(GL_FALSE); // disable writing to depth buffer
  glDisable(GL_DEPTH_TEST);

  int screenWidth = viewer->size().width();
  int screenHeight = viewer->size().height();
  
  viewer->startScreenCoordinatesSystem();

  for(int i=0; i<m_screenboxes.count(); i++)
    {
      QString str;
      ScreenBoxGrabber *cmg = m_screenboxes[i];

      QPointF pos = cmg->position();      
      float sx, sy;
      cmg->size(sx, sy);

      float s0x = pos.x()*screenWidth;
      float s0y = pos.y()*screenHeight;
      sx *= screenWidth;
      sy *= screenHeight;

      glColor4f(0.8f, 0.8f, 0.8f, 0.8f);
      if (cmg->grabsMouse())
	glColor4f(0.5f, 0, 0, 0.8f);

      glBegin(GL_QUADS);
      glVertex3f(s0x-sx, s0y-sy, 1);
      glVertex3f(s0x+sx, s0y-sy, 1);
      glVertex3f(s0x+sx, s0y+sy, 1);
      glVertex3f(s0x-sx, s0y+sy, 1);
      glEnd();
    }

  viewer->stopScreenCoordinatesSystem();
  glMatrixMode(GL_MODELVIEW);
  glPopMatrix();  
  
  glEnable(GL_DEPTH_TEST);
  glDepthMask(GL_TRUE); // enable writing to depth buffer
  glDisable(GL_BLEND);
  glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);      
}

bool
ScreenBox::keyPressEvent(QKeyEvent *event)
{
  for(int i=0; i<m_screenboxes.count(); i++)
    {
      if (m_screenboxes[i]->grabsMouse())
	{
	  if (event->key() == Qt::Key_Delete)
	    {
	      m_screenboxes[i]->removeFromMouseGrabberPool();
	      m_screenboxes.removeAt(i);
	    }
	  else if (event->key() == Qt::Key_Space)
	    {
	      float x, y;
	      m_screenboxes[i]->size(x, y);

	      QString cmd;
	      bool ok;
	      QString mesg;
	      mesg = "Current values \n";
	      mesg += QString("size : %1 %2\n").arg(x).arg(y);
	      mesg += QString("lod : %1\n").arg(m_screenboxes[i]->lod());
	      cmd = QInputDialog::getText(0,
					  "ScreenBox Commands",
					  mesg,
					  QLineEdit::Normal,
					  "",
					  &ok);
	      if (ok && !cmd.isEmpty())
		processCommand(i, cmd); 
	    }
	}
    }
  
  return true;
}

void
ScreenBox::processCommand(int idx, QString cmd)
{
  bool ok;
  cmd = cmd.toLower();
  QStringList list = cmd.split(" ", QString::SkipEmptyParts);
  
  if (list[0] == "size")
    {
      float x, y;
      m_screenboxes[idx]->size(x, y);
      if (list.size() > 1) x = list[1].toFloat(&ok);
      if (list.size() > 2) y = list[2].toFloat(&ok);
      m_screenboxes[idx]->setSize(x, y);      
    }
  else if (list[0] == "lod")
    {
      if (list.size() > 1)
	{
	  int l = list[1].toInt(&ok);
	  if (l >0 && l <= 5)
	    m_screenboxes[idx]->setLod(l);
	}
    }
}
